package com.black.platform.user.service.handler.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.black.common.constant.ShareConstant;
import com.black.common.web.PageQuery;
import com.black.platform.organization.service.bz.OrganizationService;
import com.black.platform.position.po.UserPosition;
import com.black.platform.position.service.biz.UserPositionService;
import com.black.platform.role.po.PositionRole;
import com.black.platform.role.service.bz.PositionRoleService;
import com.black.platform.role.vo.IdVo;
import com.black.platform.user.po.ShareUser;
import com.black.platform.user.service.bz.ShareUserService;
import com.black.platform.user.service.handler.ShareUserHandlerService;
import com.black.platform.user.vo.ShareUserPositionVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author linwenfeng
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ShareUserHandlerServiceImpl implements ShareUserHandlerService {

    private final ShareUserService shareUserService;

    private final UserPositionService userPositionService;

    private final OrganizationService organizationService;

    private final PositionRoleService positionRoleService;

    @Value("${share.auth.default-password:share}")
    String defaultPassword;

    private static final BCryptPasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();


    @Override
    public IPage<ShareUser> search(PageQuery<ShareUser> searchVo) {
        if (!StringUtils.isEmpty(searchVo.getQueryData().getComCode())) {
            String powerComCode = organizationService.getPowerComCode(searchVo.getQueryData().getComCode());
            searchVo.getQueryData().setComCode(powerComCode);
        }
        return shareUserService.search(searchVo);
    }

    @Override
    public ShareUser findUserByUsername(String username) {
        return shareUserService.findUserByUsername(username);
    }

    @Override
    public ShareUserPositionVo getShareUserPositionVoByUserId(Long userId) {
        ShareUserPositionVo vo = new ShareUserPositionVo();
        ShareUser shareUser = shareUserService.getById(userId);
        vo.setShareUser(shareUser);
        QueryWrapper<UserPosition> query = new QueryWrapper<>();
        query.eq("user_id", userId);
        List<UserPosition> userPositions = userPositionService.list(query);
        vo.setPositionIds(new ArrayList<>());
        userPositions.forEach(userPosition -> {
            IdVo idVo = new IdVo(userPosition.getPositionId());
            vo.getPositionIds().add(idVo);
        });
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(ShareUserPositionVo shareUserPositionVo) {
        String password = null;
        if (shareUserPositionVo.getShareUser().getId() != null) {
            QueryWrapper<UserPosition> query = new QueryWrapper<>();
            query.eq("user_id", shareUserPositionVo.getShareUser().getId());
            userPositionService.remove(query);
            password = shareUserService.getById(shareUserPositionVo.getShareUser().getId()).getPassword();
        }
        if (StringUtils.isEmpty(password)) {
            password = defaultPassword;
            shareUserPositionVo.getShareUser().setPassword(PASSWORD_ENCODER.encode(password));
            shareUserService.save(shareUserPositionVo.getShareUser());
        } else {
            shareUserPositionVo.getShareUser().setPassword(password);
            shareUserService.updateById(shareUserPositionVo.getShareUser());
        }
        List<UserPosition> userPositionList = new ArrayList<>();
        for (int i = 0; i < shareUserPositionVo.getPositionIds().size(); i++) {
            UserPosition userPosition = new UserPosition();
            userPosition.setPositionId(shareUserPositionVo.getPositionIds().get(i).getId());
            userPosition.setUserId(shareUserPositionVo.getShareUser().getId());
            userPosition.setOrders(i + 1);
            userPositionList.add(userPosition);
        }
        return userPositionService.saveBatch(userPositionList);
    }

    @Override
    public boolean resetPassword(Long userId) {
        ShareUser user = shareUserService.getById(userId);
        if (user != null) {
            user.setPassword(PASSWORD_ENCODER.encode(defaultPassword));
        } else {
            return false;
        }
        return shareUserService.updateById(user);
    }

    @Override
    public boolean close(Long userId) {
        ShareUser user = shareUserService.getById(userId);
        if (user != null) {
            user.setValid(ShareConstant.Status.IN_VALID);
        } else {
            return false;
        }
        return shareUserService.updateById(user);
    }

    @Override
    public boolean open(Long userId) {
        ShareUser user = shareUserService.getById(userId);
        if (user != null) {
            user.setValid(ShareConstant.Status.VALID);
        } else {
            return false;
        }
        return shareUserService.updateById(user);
    }

    @Override
    public ShareUser getShareUserById(Long userId) {
        return shareUserService.getById(userId);
    }

    @Override
    public Set<Long> getShareUserHavingRoleIdByUserId(Long userId) {
        QueryWrapper<UserPosition> query = new QueryWrapper<>();
        query.eq("user_id", userId);
        query.eq("valid", ShareConstant.Status.VALID);
        List<UserPosition> userPositions = userPositionService.list(query);
        if (CollectionUtils.isEmpty(userPositions)) {
            return null;
        }
        Set<Long> positionIdSet = userPositions.stream().map(UserPosition::getPositionId).collect(Collectors.toSet());
        QueryWrapper<PositionRole> roleQuery = new QueryWrapper<>();
        roleQuery.in("position_id", positionIdSet);
        roleQuery.eq("valid", ShareConstant.Status.VALID);
        List<PositionRole> list = positionRoleService.list(roleQuery);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.stream().map(PositionRole::getRoleId).collect(Collectors.toSet());
    }

    @Override
    public ShareUser findUserByOtherId(String otherId, String idType) {
        if (ShareConstant.ThirdPartyId.OPEN_ID.equals(idType)){
            return this.shareUserService.getOne(new LambdaQueryWrapper<ShareUser>().eq(ShareUser::getOpenId,otherId));
        }else if (ShareConstant.ThirdPartyId.UNION_ID.equals(idType)){
            return this.shareUserService.getOne(new LambdaQueryWrapper<ShareUser>().eq(ShareUser::getUnionId,otherId));
        }
        return null;
    }

    @Override
    public ShareUser register(ShareUser shareUser) {
        if (StringUtils.isEmpty(shareUser.getPassword())){
            shareUser.setPassword("password");
        }
        boolean save = shareUserService.save(shareUser);
        if (save){
            return shareUser;
        }
        return null;
    }
}
